// 临时数组
const roots = [-1, -1, -1];
const PI2 = Math.PI * 2;
// 非0环绕数规则判断一个点是否位于多边形内部
export function windingLine(
  x0: number,
  y0: number,
  x1: number,
  y1: number,
  x: number,
  y: number
): number {
  if ((y > y0 && y > y1) || (y < y0 && y < y1)) {
    return 0;
  }
  // Ignore horizontal line
  if (y1 === y0) {
    return 0;
  }
  const t = (y - y0) / (y1 - y0);
  let dir = y1 < y0 ? 1 : -1;
  // Avoid winding error when intersection point is the connect point of two line of polygon
  if (t === 1 || t === 0) {
    dir = y1 < y0 ? 0.5 : -0.5;
  }
  const x_ = t * (x1 - x0) + x0;
  // If (x, y) on the line, considered as "contain".
  return x_ === x ? Infinity : x_ > x ? dir : 0;
}
export function windingArc(
  cx: number,
  cy: number,
  r: number,
  startAngle: number,
  endAngle: number,
  anticlockwise: boolean,
  x: number,
  y: number
) {
  y -= cy;
  if (y > r || y < -r) {
    return 0;
  }
  const tmp = Math.sqrt(r * r - y * y);
  roots[0] = -tmp;
  roots[1] = tmp;

  const dTheta = Math.abs(startAngle - endAngle);
  if (dTheta < 1e-4) {
    return 0;
  }
  if (dTheta >= PI2 - 1e-4) {
    // Is a circle
    startAngle = 0;
    endAngle = PI2;
    const dir = anticlockwise ? 1 : -1;
    if (x >= roots[0] + cx && x <= roots[1] + cx) {
      return dir;
    } else {
      return 0;
    }
  }

  if (startAngle > endAngle) {
    // Swap, make sure startAngle is smaller than endAngle.
    const tmp = startAngle;
    startAngle = endAngle;
    endAngle = tmp;
  }
  // endAngle - startAngle is normalized to 0 - 2*PI.
  // So following will normalize them to 0 - 4*PI
  if (startAngle < 0) {
    startAngle += PI2;
    endAngle += PI2;
  }

  let w = 0;
  for (let i = 0; i < 2; i++) {
    const x_ = roots[i];
    if (x_ + cx > x) {
      let angle = Math.atan2(y, x_);
      let dir = anticlockwise ? 1 : -1;
      if (angle < 0) {
        angle = PI2 + angle;
      }
      if (
        (angle >= startAngle && angle <= endAngle) ||
        (angle + PI2 >= startAngle && angle + PI2 <= endAngle)
      ) {
        if (angle > Math.PI / 2 && angle < Math.PI * 1.5) {
          dir = -dir;
        }
        w += dir;
      }
    }
  }
  return w;
}
